package io.renren.service;

import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.cipher.RSASigner;
import com.wechat.pay.java.core.cipher.Signer;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.util.IOUtil;
import com.wechat.pay.java.core.util.PemUtil;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;

import java.io.IOException;
import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * JsapiService使用示例
 */
public class JsapiServiceExample {

    public static String appid = "wx8cd282afbaaaa274";

    /**
     * 商户号
     */
    public static String merchantId = "1717390286";

    /**
     * 商户API私钥路径
     */
    public static String privateKeyPath = "/Users/lidong/Work/projects/yanchengapi/renren-security/renren-api/src/main/resources/jsapi_cert/apiclient_key.pem";

    /**
     * 商户证书序列号
     */
    public static String merchantSerialNumber = "46AC485E1F23D4BEBF50A18277EA070F4BC6DB73";

    /**
     * 商户APIV3密钥
     */
    public static String apiV3Key = "UQtXwykPKSGguiM6cYZFE7swg1hwATd5";

    public static JsapiService service;

    public static void main(String[] args) {
        // 初始化商户配置
        Config config =
                new RSAAutoCertificateConfig.Builder()
                        .merchantId(merchantId)
                        // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥，商户私钥会用来生成请求的签名
                        .privateKeyFromPath(privateKeyPath)
                        .merchantSerialNumber(merchantSerialNumber)
                        .apiV3Key(apiV3Key)
                        .build();

        // 初始化服务
        service = new JsapiService.Builder().config(config).build();
        // ... 调用接口
        PrepayResponse prepay = prepay();


        /**
         * 下面为使用加密获取密钥,也需要返回给前段
         */
        long timeStamp = System.currentTimeMillis() / 1000;
        String nonceStr = UUID.randomUUID().toString().replace("-", "");
        //构造签名参数(appid更换为实际支付人员的appid)
        String prepay_id = prepay.getPrepayId();
        String message = appid + "\n" + timeStamp + "\n" + nonceStr + "\n" + "prepay_id=" + prepay_id + "\n";

        //生成签名
        try {
            String keyString = IOUtil.loadStringFromPath(privateKeyPath);
            PrivateKey privateKey = PemUtil.loadPrivateKeyFromString(keyString);
            Signer rsaSigner = new RSASigner(merchantSerialNumber, privateKey);
            String sign = rsaSigner.sign(message).getSign();
            //前段通过该签名可以调用支付
//            System.out.println("sign==>" + sign);
//            System.out.println("message==>" + message);
            /**
             * 注意:
             * 1.预支付订单号(prepay_id),以及生成签名的timeStamp,nonceStr的参数都需要返回前端
             * 2.在构造签名参数的时候,\n一定要加 否则也是签名无效
             * 3.
             */
            Map<String, String> params = new HashMap<>();
            params.put("paySign", sign);
            params.put("package", "prepay_id=" + prepay_id);
            params.put("nonceStr", nonceStr);
            params.put("timeStamp", "" + timeStamp);
            System.out.println(params);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


        try {
            closeOrder();
        } catch (HttpException e) { // 发送HTTP请求失败
            // 调用e.getHttpRequest()获取请求打印日志或上报监控，更多方法见HttpException定义
        } catch (ServiceException e) { // 服务返回状态小于200或大于等于300，例如500
            // 调用e.getResponseBody()获取返回体打印日志或上报监控，更多方法见ServiceException定义
        } catch (MalformedMessageException e) { // 服务返回成功，返回体类型不合法，或者解析返回体失败
            // 调用e.getMessage()获取信息打印日志或上报监控，更多方法见MalformedMessageException定义
        }
    }

    /**
     * 关闭订单
     */
    public static void closeOrder() {

        CloseOrderRequest request = new CloseOrderRequest();
        // 调用request.setXxx(val)设置所需参数，具体参数可见Request定义
        // 调用接口
        service.closeOrder(request);
    }

    /**
     * JSAPI支付下单
     */
    public static PrepayResponse prepay() {
        PrepayRequest request = new PrepayRequest();
        // 调用request.setXxx(val)设置所需参数，具体参数可见Request定义
        Amount amount = new Amount();
        //设置金额, 以分为单位 金额根据实际情况自行填写
        amount.setTotal(1);
        amount.setCurrency("CNY");
        request.setAmount(amount);
        //绑定微信支 公众号的appid 根据实际情况自行获取填写
        request.setAppid(appid);
        // 商户系统内部订单号，只能是数字、大小写字母_-*且在同一个商户号下唯一,根据自己需求自己定义
        request.setMchid(merchantId);
        request.setDescription("产品描述");
        //支付成功后回调的URL
        request.setNotifyUrl("https://notify_url");
        //ZHE
        request.setOutTradeNo("out_trade_no_001");

        //自定义信息, 在支付订单回调可以取到(自行替换,如不需要可注释掉)
//        Map<String,Object> map = new HashMap<>();
//        map.put("key", "value");
//        request.setAttach(map.toString());
        Payer payer = new Payer();
        //支付人员的的openid
        payer.setOpenid("o6SAF7CJDmMK9GZIZxHgtPLpfua0");
        request.setPayer(payer);
        //调用支付接口
        PrepayResponse response = service.prepay(request);
        //响应体中有预支付订单号
        System.out.println(response.getPrepayId());
        //以上为获取预支付订单号步骤
        return response;
    }

    /**
     * 微信支付订单号查询订单
     */
    public static Transaction queryOrderById() {

        QueryOrderByIdRequest request = new QueryOrderByIdRequest();
        // 调用request.setXxx(val)设置所需参数，具体参数可见Request定义
        // 调用接口
        return service.queryOrderById(request);
    }

    /**
     * 商户订单号查询订单
     */
    public static Transaction queryOrderByOutTradeNo() {

        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        // 调用request.setXxx(val)设置所需参数，具体参数可见Request定义
        // 调用接口
        return service.queryOrderByOutTradeNo(request);
    }
}